﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Playables;
using UnityEngine.Timeline;

public class TimeLineCtrl : MonoBehaviour
{
    private PlayableDirector director;
    private Transform track;
    private Action stopCallback;
    private SignalTrack signalTrack;

    private void LoadTimeLine()
    {
        GameObject gob = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/AssetsPackage/TimeLine/timeLine.prefab");
        GameObject timeLineGob = Instantiate(gob);
        director = timeLineGob.GetComponent<PlayableDirector>();
        director.stopped += OnTimeLineStoped;
        // TimelineAsset asset1 = TimelineAsset.CreateInstance<TimelineAsset>();
        // director.playableAsset = asset1;
        addCustomSignalEvent();
    }

    /// <summary>
    /// 自定义事件轨道
    /// </summary>
    private void addCustomSignalEvent()
    {
        TimelineAsset asset = director.playableAsset as TimelineAsset;
        signalTrack = asset.CreateTrack<SignalTrack>();
        SignalReceiver receiver = gameObject.AddComponent<SignalReceiver>();
        //把组件绑定到轨道上
        director.SetGenericBinding(signalTrack, gameObject);
        //在时间点3处创建事件
        SignalAsset signalAsset = new SignalAsset();
        signalAsset.name = "skill";
        SignalEmitter signalEmit = signalTrack.CreateMarker<SignalEmitter>(3);
        signalEmit.asset = signalAsset;
        //创建委托
        receiver.AddReaction(signalEmit.asset, new UnityEvent());
        //给委托添加回调
        receiver.GetReaction(signalAsset).AddListener(() =>
        {
            Debug.Log("======skill事件被触发======");
        });
    }

    /// <summary>
    /// 代码中手动添加的轨道需要在退出时候给释放掉，否则轨道会被保存到预制体中
    /// </summary>
    public void RemoveTrace()
    {
        if (this.signalTrack != null)
        {
            TimelineAsset asset = director.playableAsset as TimelineAsset;
            asset.DeleteTrack(this.signalTrack);
            this.signalTrack = null;
        }
    }

    private void OnTimeLineStoped(PlayableDirector obj)
    {
        stopCallback?.Invoke();
    }


    public void BindTimeLine(Transform moveTarget, Transform transFrom, Transform transEnd)
    {
        if (this.director == null)
        {
            LoadTimeLine();
        }
        track = moveTarget;
        track.position = transFrom.position;
        foreach (PlayableBinding output in director.playableAsset.outputs)
        {
            if (output.sourceObject is CustomMoveTrack customTrack)
            {
                director.SetGenericBinding(output.sourceObject, track);
                
                foreach (var clip in customTrack.GetClips())
                {
                    var moveClip = clip.asset as MoveClip;
                    director.SetReferenceValue(moveClip.startLocation.exposedName, transFrom);
                    director.SetReferenceValue(moveClip.endLocation.exposedName, transEnd);
                }
            }
        }
    }

    public void PlayTimeLine(Action stopCallback = null)
    {
        this.stopCallback = stopCallback;
        director.Play();
    }

    // Update is called once per frame
    void Update()
    {
        
        
    }

    private void OnDestroy()
    {
        RemoveTrace();
    }
}
